package co.edu.unal.geditor.controller;

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileFilter;

import co.edu.unal.geditor.model.Drawing;

import co.edu.unal.geditor.view.Canvas;
import co.edu.unal.geditor.view.MainFrame;
import co.edu.unal.geditor.view.tools.Tool;

public class App
{
	//TODO: No modificar clases que esten relacionadas al trabajo que otra persona ya se asigno
	//Martinn wiii
	//TODO: TextMode:Jairo
	// singleton design pattern + lazy initialization (better)
	public synchronized static App getInstance()
	{
		while ( m_this == null )
		{
			m_this = new App();
		}

		return m_this;
	}

	// default constructor: private
	private App()
	{
		m_drawing = new Drawing();
		m_mframe = new MainFrame();
	}

	public MainFrame getMainFrame()
	{
		return m_mframe;
	}

	public Drawing getDrawing()
	{
		return m_drawing;
	}

	public Canvas getCanvas()
	{
		return m_mframe.getCanvas();
	}

	public void run()
	{
		m_mframe.init();
		m_mframe.setTitle( "Graph Editor v1.0" );
		m_mframe.setExtendedState( Frame.MAXIMIZED_BOTH );
		m_mframe.setVisible( true );

		// new in v0.8
		m_drawing.init();
		// new in v0.8
	}

	// render the document (collaboration: Drawing)
	public void paint( Graphics g )
	{
		m_drawing.paint( g );
	}

	public void newDocument()
	{	
		if(saveDocumentIfNeeded()){
			m_drawing.setFileName(null);
			m_drawing.init();
			m_drawing.clear();
			m_drawing.setFillingColor(Color.white);
			m_drawing.setcolorBackground(Color.white);
			m_drawing.setLinesColor(Color.black);
			m_mframe.setStatus(null);
			m_mframe.setTitle( "Graph Editor v0.8" );
			
		}
		else{
			//do nothing
		}
		
	}


	// save document (collaboration: Drawing)
	public boolean saveDocument()
	{
		String sFileName = null;

		// document already saved?
		if ( m_drawing.getFileName() == null )
		{
			// no, open file chooser dialog
			JFileChooser fc = new JFileChooser( System.getProperty( "user.home", "./" ) );

			// Note: showSaveDialog() used here
			if ( fc.showSaveDialog( m_mframe ) == JFileChooser.APPROVE_OPTION )
			{
				sFileName = fc.getSelectedFile().getAbsolutePath();

				// make sure file name ends with .gef
				if ( sFileName.endsWith( Drawing.EXT ) == false )
				{
					sFileName += Drawing.EXT;
				}
			}
		}
		else
		{
			sFileName = m_drawing.getFileName();
		}

		boolean bSavedOk = false;

		if ( sFileName != null )
		{
			try
			{
				ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream( sFileName ) );
				bSavedOk = m_drawing.save( oos );
				oos.close();
			}
			catch ( Exception exc )
			{
				JOptionPane.showMessageDialog( m_mframe, "Save document failed: " + exc );
			}
		}

		if ( bSavedOk )
		{
			m_drawing.setFileName( sFileName );
			m_mframe.setTitle( m_mframe.getTitle() + " - " + m_drawing.getFileName() );
			m_mframe.setStatus( "Drawing successfully saved." );
		}

		return bSavedOk;
	}

	public boolean saveDocumentAs()
	{
		boolean bSavedOk = false;

		String sFileName = null;
		
		JFileChooser fc = new JFileChooser( System.getProperty( "user.home", "./" ) );
		
		if ( fc.showSaveDialog( m_mframe ) == JFileChooser.APPROVE_OPTION )
		{
			sFileName = fc.getSelectedFile().getAbsolutePath();


			// make sure file name ends with .gef
			if ( sFileName.endsWith( Drawing.EXT ) == false )
			{
				sFileName += Drawing.EXT;
			}
		}
		
		if ( sFileName != null )
		{
			try
			{
				ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream( sFileName ) );
				bSavedOk = m_drawing.save( oos );
				oos.close();
			}
			catch ( Exception exc )
			{
				JOptionPane.showMessageDialog( m_mframe, "Save document failed: " + exc );
			}
		}
		
		if ( bSavedOk )
		{
			m_drawing.setFileName( sFileName );
			m_mframe.setTitle( m_mframe.getTitle() + " - " + m_drawing.getFileName() );
			m_mframe.setStatus( "Drawing successfully saved." );
		}

		return bSavedOk;
	}

	public boolean openDocument()
	{
		boolean bLoadedOk = false;
		String sFileName = null;

		if ( saveDocumentIfNeeded() )
		{
			JFileChooser fc = new JFileChooser( System.getProperty( "user.home", "./" ) );
			fc.setFileFilter( new FileFilter()
			{
				public boolean accept( File f )
				{
					return (f.isDirectory() || f.getName().endsWith( Drawing.EXT ));
				}

				public String getDescription()
				{
					return "Graph Editor files" + " (*" + Drawing.EXT + ")";
				}
			} );

			// Note: showOpenDialog() used here
			if ( fc.showOpenDialog( m_mframe ) == JFileChooser.APPROVE_OPTION )
			{
				sFileName = fc.getSelectedFile().getAbsolutePath();

				try
				{
					ObjectInputStream ois = new ObjectInputStream( new FileInputStream( sFileName ) );
					bLoadedOk = m_drawing.open( ois );
					ois.close();
				}
				catch ( Exception exc )
				{
					JOptionPane.showMessageDialog( m_mframe, "Open document failed: " + exc );
				}
			}
		}

		if ( bLoadedOk )
		{
			assert sFileName != null;
			
			m_drawing.setFileName( sFileName );
			m_drawing.clearUndoManager();
			m_mframe.setTitle( m_mframe.getTitle() + " - " + m_drawing.getFileName() );
			m_mframe.setStatus( "Drawing successfully loaded." );
		}
		else
		{
			JOptionPane.showMessageDialog( m_mframe, "Open document failed !", "Error !", JOptionPane.ERROR_MESSAGE );
		}

		return bLoadedOk;
	}

	// set active tool (collaboration: Drawing)
	// PRE-CONDITION: tool != null
	// POST-CONDITION: active tool changed
	public void setActiveTool( Tool tool )
	{
		assert tool != null;

		m_mframe.setActiveTool( tool );
	}

	protected boolean saveDocumentIfNeeded()
	{
		boolean bOkToContinue = true;

		// document modified since last save?
		if ( m_drawing.isModified() )
		{
			int r = JOptionPane.showConfirmDialog( m_mframe, "The document has been modified since last save.\n\n"
				+ "Do you want to save it before exiting?\n\n" );

			if ( r == JOptionPane.CANCEL_OPTION )
			{
				bOkToContinue = false;
			}
			else if ( r == JOptionPane.NO_OPTION )
			{
				// exit w/out saving
			}
			else if ( r == JOptionPane.YES_OPTION )
			{
				// bOkToContinue = false : don't exit (retry if saveDocument() fails)
				// TODO: how many retries?
				bOkToContinue = saveDocument();
			}
		}

		return bOkToContinue;
	}

	public void undo()
	{
		m_drawing.undo();
	}

	public void redo()
	{
		m_drawing.redo();
	}
	
	public void exit()
	{
		if ( saveDocumentIfNeeded() )
		{
			System.exit( 0 );
		}
		else
		{
			// Do nothing
		}
	}
	public void delete(){
		m_drawing.delete();
	}

	public static void main( String[] args )
	{
		App.getInstance().run();
	}
	
	

	private static App m_this;

	private Drawing m_drawing;
	private MainFrame m_mframe;
}
